// 你这个学期必须选修 numCourses 门课程，记为 0 到 numCourses - 1 。

// 在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出，其中 prerequisites[i] = [ai, bi] ，表示如果要学习课程 ai 则 必须 先学习课程  bi 。

// 例如，先修课程对[0, 1] 表示：想要学习课程 0 ，你需要先完成课程 1 。
// 请你判断是否可能完成所有课程的学习？如果可以，返回 true ；否则，返回 false 。

// 示例 1：

// 输入：numCourses = 2, prerequisites = [[1, 0]]
// 输出：true
// 解释：总共有 2 门课程。学习课程 1 之前，你需要完成课程 0 。这是可能的。

// 方法：拓扑排序

/**
 * @param {number} numCourses
 * @param {number[][]} prerequisites
 * @return {boolean}
 */
var canFinish = function (numCourses, prerequisites) {
    const inDegree = new Array(numCourses).fill(0);
    let map = new Map();
    for (let i = 0; i < prerequisites.length; i++) {
        const curArr = prerequisites[i];
        inDegree[curArr[0]]++;
        if (map.has(curArr[1])) {
            map.set(curArr[1], [...map.get(curArr[1]), curArr[0]]);
        } else  {
            map.set(curArr[1], [curArr[0]]);
        }
    }

    const queue = [];
    // 所有入度为0的结点入队
    for (let i = 0; i < inDegree.length; i++) {
        if (inDegree[i] === 0)
            queue.push(i);
    }
    let cnt = 0;
    while (queue.length) {
        const selected = queue.shift();
        cnt++;
        const toEnQueue = map.get(selected);
        if (toEnQueue && toEnQueue.length) {
            for (let i = 0; i < toEnQueue.length; i++) {
                inDegree[toEnQueue[i]]--;
                if (inDegree[toEnQueue[i]] === 0)
                    queue.push(toEnQueue[i]);
            }
        }
    }

    return cnt === numCourses;
};

const numCourses = 2, prerequisites = [[1, 0], [0, 1]];
const res = canFinish(numCourses, prerequisites);
console.log(res);